package com.zang.blogz.service.impl;

import cn.dev33.satoken.exception.NotPermissionException;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zang.blogz.constant.AuthorConstant;
import com.zang.blogz.constant.RedisConstant;
import com.zang.blogz.constant.ResultConstant;
import com.zang.blogz.entity.Menu;
import com.zang.blogz.entity.UserInfo;
import com.zang.blogz.mapper.MenuMapper;
import com.zang.blogz.model.input.ro.MenuRO;
import com.zang.blogz.model.output.UserMenuVO;
import com.zang.blogz.result.Result;
import com.zang.blogz.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.zang.blogz.utils.BeanCopyUtils;
import com.zang.blogz.utils.UserInfoUtil;

import io.github.vampireachao.stream.core.optional.Opp;
import io.github.vampireachao.stream.core.stream.Steam;
import io.github.vampireachao.stream.plugin.mybatisplus.Database;
import io.github.vampireachao.stream.plugin.mybatisplus.Many;
import io.github.vampireachao.stream.plugin.mybatisplus.One;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.Set;


/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 朵橙i
 * @since 2022-06-17
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {

    @Autowired
    private UserRoleService userRoleService;


    @Autowired
    private RoleMenuService roleMenuService;

    @Autowired
    private RedisService redisService;

    @Override
    public List<UserMenuVO> queryUserMenu() {

        Integer userId = UserInfoUtil.getLoginUserId();

        Object o = redisService.get(userId + ":" + RedisConstant.USER_MENU);

        if (Opp.of(o).isPresent()) {

            return JSONUtil.toList(o.toString(), UserMenuVO.class);
        }

        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();

        List<Integer> ids = userRoleService.getRoleIdsByLoginAdmin(userId);

        List<Integer> menuIds = Steam.of(roleMenuService.getMenuIds(ids)).distinct().toList();

        queryWrapper.in(Menu::getId, menuIds);

        List<Menu> list = list(queryWrapper);

        List<UserMenuVO> userMenuVos;
        userMenuVos = BeanCopyUtils.copyList(list, UserMenuVO.class);

        List<UserMenuVO> menuVos = Steam.of(userMenuVos).toTree(UserMenuVO::getId, UserMenuVO::getParentId, UserMenuVO::setMenus);

        redisService.set(userId + ":" + RedisConstant.USER_MENU, JSONUtil.toJsonStr(menuVos));

        return menuVos;
    }

    @Override
    public List<UserMenuVO> getMenuTreeBy() {


        Object o = redisService.get(RedisConstant.USER_MENU);

        if (Opp.of(o).isPresent()) {

            return JSONUtil.toList(o.toString(), UserMenuVO.class);
        }


        List<Menu> menuList = list();

        List<UserMenuVO> menuVOS = BeanCopyUtils.copyList(menuList, UserMenuVO.class);

        List<UserMenuVO> vos = Steam.of(menuVOS).toTree(UserMenuVO::getId,
                UserMenuVO::getParentId,
                UserMenuVO::setMenus,
                (s) -> Objects.equals(s.parentId, null));


        redisService.set(RedisConstant.USER_MENU, JSONUtil.toJsonStr(vos));

        return vos;
    }

    @Override
    public Result<MenuRO> saveMenu(MenuRO menuRO) {

        boolean save = save(menuRO);

        if (save){

            return Result.ok(ResultConstant.SAVE_SUCCESS, menuRO);
        }

        return Result.error(ResultConstant.SAVE_FAIL, menuRO);
    }

    @Override
    public Result<MenuRO> updateMenu(MenuRO menuRO) {

        if (updateById(menuRO)){

            return Result.ok(ResultConstant.UPDATE_SUCCESS, menuRO);
        }else {
            return Result.ok(ResultConstant.UPDATE_FAIL, menuRO);
        }
    }

    @Override
    public Result<Boolean> deleteMenu(Integer id) {

        Set<String> authorSet = AuthorConstant.authorSet;

        Integer loginUserId = UserInfoUtil.getLoginUserId();

        String userName = One.of(UserInfo::getId).eq(loginUserId).value(UserInfo::getNickname).query();

        boolean flag;

        if (!authorSet.contains(userName)){

            int parentIdSize = Many.of(Menu::getParentId).eq(id).query().size();

            if (parentIdSize > 0){

                throw new RuntimeException("当前菜单下含有子菜单无法删除");
            }else {

                flag =  Database.removeById(id,Menu.class);
            }
        }else {

            throw new NotPermissionException("你没有当前权限不能删除日志");
        }

        return Result.ok(ResultConstant.DELETE_SUCCESS, flag);
    }


}
